import { defineStore } from 'pinia'
import type { LoginParamsData, UserInfoData } from '@/api/userInfo'
import { default as userInfoApi } from '@/api/userInfo'
import {allAsyncRoutes, anyRoute, staticRoutes} from '@/router/routes'
import type { RouteRecordRaw } from 'vue-router'
import router from '@/router'
import cloneDeep from 'lodash/cloneDeep'


interface UserInfoStoreStateData {
  token: string,
  userInfo: UserInfoData,
  menuRoutes:Array<RouteRecordRaw>
}


function initUserInfo(target: UserInfoData, source: UserInfoData) {
  Object.assign(target, source)
}



// 定义函数从所有的异步路由当中过滤当前用户的异步路由
// 参数一是所有的异步路由,参数二是根据token返回的独有的异步路由
function filterAllAsyncRouter(allAsyncRoutes:RouteRecordRaw[],myRouter:string[]){
  let asyncRouters = allAsyncRoutes.filter(item=>{
    if(myRouter.includes(item.name as string)){
      if(item.children&&item.children.length){
        item.children = filterAllAsyncRouter(item.children,myRouter)
      }
      return true
    }
  })
  return asyncRouters
}

// 封装可以一次性添加多个路由的工具函数
// 更具router的addRoute重新封装了一个可以添加多个路由的函数
function addRoutes(asyncOrAnyRoute:RouteRecordRaw[]){
  asyncOrAnyRoute.forEach(item=>{
    router.addRoute(item)
  })
}

// 当用户退出登录的时候，我们需要重置路由  没有参数
function resetRoutes(){
// 将router里的所有的路由全部删除
//  先获取全部的路由
  let allRoutes = router.getRoutes()
  // 饭后根据这个allRoutes遍历删除所有的路由
  allRoutes.forEach(item=>{
    router.removeRoute(item.name as string)
  })
  // 最后添加静态路由
  addRoutes(staticRoutes)
}





export const useUserInfoStore = defineStore('userInfo', {
  // 核心概念
  state: (): UserInfoStoreStateData => {
    return {
      // token到时候要和自动登录（免登录）相关联
      // 存储token到localStorage持久化存储
      // cookie  localStorage  sessionStorage的区别
      token: localStorage.getItem('token_key') || '',
      userInfo: {
        routes: [],
        buttons: [],
        roles: [],
        name: '',
        avatar: ''
      },
      menuRoutes:staticRoutes
    }
  },
  actions: {
    async login(loginParams: LoginParamsData) {
      try {
        const result = await userInfoApi.userLogin(loginParams)
        this.token = result.token  //把token保存在state
        // 要自动登录还得把token保存到localStorage
        localStorage.setItem('token_key', result.token)

        // 如果登录成功，我们还要写一个正常的返回值，让async函数返回的promise是成功的
        // 后面根据这个值来判断登录成功还是失败，再去做后续的操作
        return 'ok'
      } catch (error) {
        return Promise.reject('登录失败')
      }
    },

    // 根据token获取用户信息
    async getUserInfo() {
      try {
        const result = await userInfoApi.getUserInfo()
        this.userInfo = result 
        // 获取返回的路由权限数组
        let routeNames = result.routes
        // 过滤获取用户自己的异步路由
        let usersAsyncRoutes = filterAllAsyncRouter(cloneDeep(allAsyncRoutes),routeNames)
        // 注入动态和任意路由
        addRoutes(usersAsyncRoutes.concat(anyRoute))
        // 上面的动态添加我们也可以叫动态注册，注册上路由是让用户点击的时候有跳转功能
        // 但是并不能显示出菜单，显示菜单要依靠的是上面state当中的menuRoutes这个数据
        // 所以我们还要把menuRoutes这个数据给修改了
        this.menuRoutes=staticRoutes.concat(usersAsyncRoutes,anyRoute)
        return 'ok'
      } catch (error) {
        return Promise.reject('获取用户信息失败')
      }
    },

    async reset() {
      this.token = ''
      initUserInfo(this.userInfo, {
        routes: [],
        buttons: [],
        roles: [],
        name: '',
        avatar: ''
      })
      localStorage.removeItem('token_key')
    },

    async logout() {
      try {
        await userInfoApi.userLogout()
        // 退出成功我们需要把state当中的用户信息和token全部清除
        // 也得把localStorage当中的token给清除
        // 重置路由
        resetRoutes()
        this.reset()
        return 'ok'
      } catch (error) {
        return Promise.reject('退出失败')
      }
    }
  },
  getters: {

  }
})